﻿using System;
using System.Linq;
using System.Collections.Generic;
using Domain.Core;
using Domain.MainModule.Entities;
using Domain.MainModule.Phones;
using Domain.MainModule.PhoneTypes;

namespace Application.MainModule.PhonesManagement
{
    public class PhoneManagementService : IPhoneManagementService, IDisposable
    {
        #region private properties

        private IPhoneRepository PhoneRepository
        {
            get;
            set;
        }

        private IPhoneTypeRepository PhoneTypeRepository
        {
            get;
            set;
        }
        
        #endregion

        #region constructor

        /// <summary>
        /// Default constructor for PhoneService.
        /// </summary>
        /// <param name="phoneRepository">PhoneRepository dependency, usually this is resolved by IoC</param>
        public PhoneManagementService(IPhoneRepository phoneRepository, IPhoneTypeRepository phoneTypeRepository)
        {
            if (phoneRepository == (IPhoneRepository)null)
            {
                throw new ArgumentNullException(Resources.Messages.exception_DependenciesAreNotInitialized);
            }

            if (phoneTypeRepository == (IPhoneRepository)null)
            {
                throw new ArgumentNullException(Resources.Messages.exception_DependenciesAreNotInitialized);
            }

            this.PhoneRepository = phoneRepository;
            this.PhoneTypeRepository = phoneTypeRepository;
        }

        #endregion

        #region IPhoneService implementations

        public void AddPhone(Phone phone)
        {
            IUnitOfWork unitOfWork = this.PhoneRepository.UnitOfWork as IUnitOfWork;
            this.PhoneRepository.Add(phone);
            unitOfWork.Commit();
        }

        public void ChangePhone(Phone phone)
        {
            IUnitOfWork unitOfWork = this.PhoneRepository.UnitOfWork as IUnitOfWork;
            this.PhoneRepository.Modify(phone);
            unitOfWork.CommitAndRefreshChanges();
        }

        public Phone FindPhoneById(Guid phoneId)
        {
            PhoneIdSpecification phoneIdSpecification = new PhoneIdSpecification(phoneId);
            return this.PhoneRepository.FindPhone(phoneIdSpecification);
        }

        public List<Phone> FindPhoneByUserId(Guid userId)
        {
            PhoneUserIdSpecification phoneUserIdSpecification = new PhoneUserIdSpecification(userId);
            return this.PhoneRepository.FindPhones(phoneUserIdSpecification).ToList<Phone>();
        }

        public void RemovePhone(Phone phone)
        {
            if (phone == (Phone)null)
            {
                throw new ArgumentNullException("phone");
            }


            IUnitOfWork unitOfWork = this.PhoneRepository.UnitOfWork as IUnitOfWork;
            this.PhoneRepository.Remove(phone);
            unitOfWork.CommitAndRefreshChanges();

        }

        public List<PhoneType> FindPhoneTypesByName(string phoneTypeName)
        {
            PhoneTypeNameSpecification specification = new PhoneTypeNameSpecification(phoneTypeName);

            return this.PhoneTypeRepository.GetBySpec(specification).ToList();
        }

        #endregion

        #region IDisposable implementations

        /// <summary>
        /// Dispose associated context with this domain service.
        /// </summary>
        public void Dispose()
        {
            if (this.PhoneRepository != null
                &&
                this.PhoneRepository.UnitOfWork != null)
            {
                this.PhoneRepository.UnitOfWork.Dispose();
            }
        }

        #endregion
    }
}
